package com.corpgovernment.common.passport;


import com.corpgovernment.common.passport.bo.PassportConvertBO;
import com.corpgovernment.common.passport.client.OrganizationPassportClient;
import com.corpgovernment.common.passport.context.PassportSpringContext;
import com.corpgovernment.common.passport.dataloader.MbPassportWarnInfoDataLoader;
import com.corpgovernment.common.passport.entity.MbPassportWarnInfo;
import com.corpgovernment.common.passport.util.NameUtil;
import com.ctrip.corp.obt.generic.utils.JsonUtils;
import com.ctrip.corp.obt.generic.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;

import java.util.Objects;
import java.util.Set;


/***
 * @author zwmao
 * @version 1.0.0
 * @date 2023/9/4
 **/
@Slf4j
public class PassportConvertUtil {
    private static final String HAS_PROBLEM = "1";
    private static final String NON_PROBLEM = "0";
    private static final String ALL_NON_PROBLEM = "0000";


    public static PassportConvertBO convertPassport(String nationality, String cnName, String enName, Integer cardType){
        log.info("【姓名取反】nationCode={} passengerName={} passport={} cardType={}",nationality, cnName, enName, cardType);
        String result = convertEnName(nationality, cnName, enName, cardType);
        if(result == null){
            log.info("姓名取反异常");
            return null;
        }
        log.info("姓名取反成功");
        return new PassportConvertBO(result);
    }

    public static boolean confirmPassport(String fromName, String toName){
        log.info("【姓名核对】需要核对的姓名为{},{}",fromName,toName);
        boolean confirmStatus = confirmEnName(fromName, toName);
        log.info("姓名核对完成，核对状态为{}", JsonUtils.toJsonString(confirmStatus));
        return confirmStatus;
    }

    public static PassportConvertBO convertPassport(String cnName, String enName){
        log.info("【姓名取反】cnName={} enName={}",cnName, enName);
        PassportConvertBO result = convertEnName(cnName, enName);
        if(result.getConvertedPassport() == null){
            log.info("姓名取反异常");
            return null;
        }
        log.info("姓名取反成功");
        return result;
    }


    public static String convertEnName(String nationality, String cnName, String enName, Integer cardType) {
        //1 英文名为空则返回null
        if (enName == null) {
            log.error("【姓名取反】英文姓名为空");
            return null;
        }

        //2 英文姓名不合规则返回原始值
        if (!NameUtil.checkEnName(enName)) {
            log.warn("【姓名取反】英文姓名不合规");
            return enName;
        }

        //3 证件类型不为护照则返回原始值
        if (!NameUtil.checkCardType(cardType)) {
            log.info("【姓名取反】证件类型不为护照");
            return enName;
        }

        //4 组装
        MbPassportWarnInfo mbPassportWarnInfo = new MbPassportWarnInfo();
        mbPassportWarnInfo.setNationality(nationality);
        mbPassportWarnInfo.setCnName(cnName);
        mbPassportWarnInfo.setEnName(enName);
        mbPassportWarnInfo.setCardType(cardType);

        //5 验证其余参数
        confirmParam(mbPassportWarnInfo);

        //6 验证中英文姓名是否对应
        confirmMatch(mbPassportWarnInfo);

        //7 返回转换后的英文姓名
        String[] split = mbPassportWarnInfo.getEnName().toUpperCase().split("/");
        return split[1] + "/" + split[0];
    }

    public static boolean confirmEnName(String fromName, String toName){
        OrganizationPassportClient organizationPassportClient = PassportSpringContext.getBean(OrganizationPassportClient.class);
        if (!organizationPassportClient.getNameConfirmSwitch()){
            log.info("【姓名核对】阿波罗开关未开启");
            return StringUtils.equals(fromName, toName, true);
        }
        log.info("【姓名核对】阿波罗开关已开启");
        //1 如果任意一个参数为空，直接返回false
        if (Objects.isNull(fromName) || Objects.isNull(toName)) {
            return false;
        }
        //2 如果两个姓名均为空字符串，返回true
        if (fromName.length() == 0 && toName.length() == 0) {
            return true;
        }
        //3 如果姓名均符合规范，进入判断逻辑
        if (NameUtil.checkEnName(fromName) && NameUtil.checkEnName(toName)) {
            return NameUtil.confirmNames(fromName, toName);
        }
        //4 反之直接调用StringUtils判断
        return StringUtils.equals(fromName, toName, true);
    }

    public static PassportConvertBO convertEnName(String cnName, String enName) {
        //1 英文名为空则返回null
        if (enName == null) {
            log.error("【姓名取反】英文姓名为空");
            return new PassportConvertBO(null);
        }

        //2 英文姓名不合规则返回原始值
        if (!NameUtil.checkEnName(enName)) {
            log.warn("【姓名取反】英文姓名不合规");
            return new PassportConvertBO(enName);
        }

        String[] splitName = enName.split("/");
        String enFullName = splitName[1] + "/" + splitName[0];

        //3 中文姓名为空或中英文不完全对应则返回颠倒的英文名
        if (cnName == null || !matchCnEnNames(cnName, enName)){
            return new PassportConvertBO(enFullName);
        }

        //4 中英文完全对应则返回原始英文名
        return new PassportConvertBO(enName);

    }

    private static void confirmParam(MbPassportWarnInfo mbPassportWarnInfo) {

        StringBuilder warnType = new StringBuilder();

        //若国籍信息为空或国籍不为中文，将warnType第二位设为1，反之为0
        if (NameUtil.checkNationality(mbPassportWarnInfo.getNationality())) {
            warnType.append(NON_PROBLEM);
        } else {
            warnType.append(HAS_PROBLEM);
        }

        //若中文姓名为空或中文姓名中包含非中文字符，将warnType第四位设为1，反之为0
        if (NameUtil.checkCnName(mbPassportWarnInfo.getCnName())) {
            warnType.append(NON_PROBLEM);
        } else {
            warnType.append(HAS_PROBLEM);
        }

        //此处英文名不会为空，因此将warnType第三位设为0
        warnType.append(NON_PROBLEM);

        //若证件类型为空或证件类型不为护照，将warnType第一位设为1，反之为0
        if (NameUtil.checkCardType(mbPassportWarnInfo.getCardType())) {
            warnType.append(NON_PROBLEM);
        } else {
            warnType.append(HAS_PROBLEM);
        }

        //保存告警状态信息
        mbPassportWarnInfo.setWarnType(warnType.toString());
        //如果告警信息不为"0000"，则说明参数异常，存入告警表中
        if (!ALL_NON_PROBLEM.equals(mbPassportWarnInfo.getWarnType())) {
            insertWarnInfo(mbPassportWarnInfo);
        }
    }

    private static void confirmMatch(MbPassportWarnInfo mbPassportWarnInfo) {

        //如果告警码不为"0000"，直接返回，不需要校验是否匹配
        if (!ALL_NON_PROBLEM.equals(mbPassportWarnInfo.getWarnType())) {
            return;
        }

        //将中文姓名转换为拼音
        Set<String> cnNamePinyin;
        try {
            cnNamePinyin = NameUtil.getAllPinyin(mbPassportWarnInfo.getCnName());
        } catch (Exception e) {
            log.warn("【姓名取反】中文姓名转换拼音异常");
            return;
        }

        //去除英文姓名中间的/并颠倒顺序
        String[] split = mbPassportWarnInfo.getEnName().toUpperCase().split("/");
        String enFullName = split[1] + split[0];

        //若命中拼音集合中任意一条则匹配成功
        for (String oneName : cnNamePinyin) {
            if (enFullName.equals(oneName)) {
                return;
            }
        }

        //未命中任意一条，匹配失败，写入告警库，此时告警信息设为"1111"
        mbPassportWarnInfo.setWarnType("1111");
        insertWarnInfo(mbPassportWarnInfo);
    }

    private static void insertWarnInfo(MbPassportWarnInfo mbPassportWarnInfo){
        try {
            MbPassportWarnInfoDataLoader mbPassportWarnInfoDataLoader = PassportSpringContext.getBean(MbPassportWarnInfoDataLoader.class);
            mbPassportWarnInfoDataLoader.insert(mbPassportWarnInfo);
            log.info("【姓名取反】写入数据库成功，当前信息为{}", JsonUtils.toJsonString(mbPassportWarnInfo));
        } catch (Exception e) {
            log.error("【姓名取反】写入数据库失败");
        }
    }

    private static boolean matchCnEnNames(String cnName, String enName){
        Set<String> cnNamePinyin;
        try {
            cnNamePinyin = NameUtil.getAllPinyin(cnName);
        } catch (Exception e) {
            log.warn("【姓名取反】中文姓名转换拼音异常");
            return false;
        }
        String[] split = enName.split("/");
        String fullName = split[0] + split[1];

        for (String oneName : cnNamePinyin){
            if (fullName.equals(oneName)){
                return true;
            }
        }
        return false;
    }
}

